home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / Resources / CutePDF 2.3 / converter.exe / GNUGS / GS_TTF.PS < prev    next >
Text File  |  2002-09-23  |  55KB  |  1,789 lines

  1. %    Copyright (C) 1996, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: gs_ttf.ps,v 1.9.2.4 2002/09/22 12:43:55 igor Exp $
  14. % Support code for direct use of TrueType fonts.
  15. % (Not needed for Type 42 fonts.)
  16.  
  17. % Note that if you want to use this file without including the ttfont.dev
  18. % option when you built Ghostscript, you will need to load the following
  19. % files before this one:
  20. %    lib/gs_mgl_e.ps
  21. %    lib/gs_mro_e.ps
  22. %    lib/gs_wan_e.ps
  23.  
  24. % Thanks to B. Jackowski and GUST (the Polish TeX Users' Group) for
  25. % the glyf-splitting code.
  26.  
  27. [
  28.    /TTCMAP_DEBUG
  29.    /TTCMAP2_DEBUG
  30. ] {dup where {pop pop} { currentdict exch false def pop } ifelse} forall
  31.  
  32.  
  33. % ---------------- Font loading machinery ---------------- %
  34.  
  35. % Augment the FONTPATH machinery so it recognizes TrueType fonts.
  36.  
  37. /.scanfontheaders where {
  38.   pop /.scanfontheaders [
  39.    .scanfontheaders aload pop (\000\001\000\000*) (true*)
  40.   ] def
  41. } if
  42.  
  43. % <file> <key> .findfontvalue <value> true
  44. % <file> <key> .findfontvalue false
  45. % Closes the file in either case.
  46. /.findnonttfontvalue /.findfontvalue load def
  47. /.findfontvalue {
  48.   1 index read pop 2 index 1 index unread
  49.   dup 0 eq exch (t) 0 get eq or {
  50.         % If this is a font at all, it's a TrueType font.
  51.     dup /FontType eq {
  52.       pop closefile 42 true
  53.     } {
  54.       dup /FontName eq { pop .findttfontname } { pop closefile false } ifelse
  55.     } ifelse
  56.   } {
  57.         % Not a TrueType font.
  58.     .findnonttfontvalue
  59.   } ifelse
  60. } bind def
  61.  
  62. % <file> .findttfontname <fname> true
  63. % <file> .findttfontname false
  64. % Closes the file in either case.
  65. /.findttfontname {
  66.   .loadttfonttables
  67.   tabdict /name .knownget {
  68.     dup 8 getu32 f exch setfileposition
  69.     12 getu32 string f exch readstring pop
  70.     6 findname
  71.   } {
  72.     false
  73.   } ifelse
  74.   f closefile end end
  75. } bind def
  76.  
  77. % Load a font file that might be a TrueType font.
  78.  
  79. % <file> .loadfontfile -
  80. /.loadnonttfontfile /.loadfontfile load def
  81. /.loadfontfile {
  82.   dup read pop 2 copy unread 0 eq {
  83.         % If this is a font at all, it's a TrueType font.
  84.     .loadttfont pop
  85.   } {
  86.         % Not a TrueType font.
  87.     .loadnonttfontfile
  88.   } ifelse
  89. } bind def
  90.  
  91. % ---------------- Automatic Type 42 generation ---------------- %
  92.  
  93. % Load a TrueType font from a file as a Type 42 PostScript font.
  94. % The thing that makes this really messy is the handling of encodings.
  95. % There are 2 interacting tables that affect the encoding:
  96. %       'cmap' provides multiple maps from character codes to glyph indices
  97. %       'post' maps glyph indices to glyph names (if present)
  98. % What we need to get out of this is:
  99. %       Encoding mapping character codes to glyph names
  100. %         (the composition of cmap and post)
  101. %       CharStrings mapping glyph names to glyph indices
  102. %         (the inverse of post)
  103. % If the post table is missing, we have to take a guess based on the cmap
  104. % table.
  105.  
  106. /.loadttfontdict 50 dict dup begin
  107.  
  108. /orgXUID AladdinEnterprisesXUID def
  109. /maxstring 32000 def    % half the maximum length of a PostScript string,
  110.             % must be a multiple of 4 (for hmtx / loca / vmtx)
  111.  
  112. % Define the Macintosh standard mapping from characters to glyph indices.
  113. /MacRomanEncoding dup .findencoding def
  114. /MacGlyphEncoding dup .findencoding def
  115.  
  116. % Invert the MacRomanEncoding.
  117. /.romanmacdict 300 dict
  118. 0 1 MacRomanEncoding length 1 sub {
  119.   MacRomanEncoding 1 index get
  120.         % Stack: dict index charname
  121.   dup /.notdef ne {
  122.     exch 2 index 2 index .knownget {
  123.       dup type /arraytype eq {
  124.     [ exch aload pop counttomark 2 add -1 roll ]
  125.       } {
  126.     exch 2 array astore
  127.       } ifelse
  128.     } if 2 index 3 1 roll put
  129.   } {
  130.     pop pop
  131.   } ifelse
  132. } for def
  133.  
  134. % Define remapping for misnamed glyphs in TrueType 'post' tables.
  135. % There are probably a lot more than this!
  136. /postremap mark
  137.   /Cdot /Cdotaccent
  138.   /Edot /Edotaccent
  139.   /Eoverdot /Edotaccent
  140.   /Gdot /Gdotaccent
  141.   /Ldot /Ldotaccent
  142.   /Zdot /Zdotaccent
  143.   /cdot /cdotaccent 
  144.   /edot /edotaccent 
  145.   /eoverdot /edotaccent
  146.   /gdot /gdotaccent 
  147.   /ldot /ldotaccent
  148.   /zdot /zdotaccent 
  149. .dicttomark readonly def
  150.  
  151. % ---- Utilities ---- %
  152.  
  153. % Define a serial number for creating unique XUIDs for TrueType fonts.
  154. % We used to use the checkSumAdjustment value from the font, but this is
  155. % not reliable, since some fonts don't set it correctly.
  156. % Note that we must do this in a string to make it immune to save/restore.
  157. /xuidstring <80000000> def
  158. /curxuid {        % - curxuid <int>
  159.   0 xuidstring { exch 8 bitshift exch add } forall
  160. } bind def
  161. /nextxuid {        % - nextxuid -
  162.   3 -1 0 {
  163.     xuidstring 1 index 2 copy get dup 255 ne {
  164.       1 add put pop exit
  165.     } if pop 0 put pop
  166.   } for
  167. } bind def
  168.  
  169. % <string> <index> getu16 <integer>
  170. /getu16 {
  171.   2 copy get 8 bitshift 3 1 roll 1 add get add
  172. } bind def
  173.  
  174. % <string> <index> gets16 <integer>
  175. /gets16 {
  176.   getu16 16#8000 xor 16#8000 sub
  177. } bind def
  178.  
  179. % <string> <index> getu32 <integer>
  180. /getu32 {
  181.   2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add
  182. } bind def
  183.  
  184. % <string> <index> gets32 <integer>
  185. /gets32 {
  186.   2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add
  187. } bind def
  188.  
  189. % <string> <index> <integer> putu16 -
  190. /putu16 {
  191.   3 copy -8 bitshift put
  192.   exch 1 add exch 16#ff and put
  193. } bind def
  194.  
  195. % <string> <index> <integer> putu32 -
  196. /putu32 {
  197.   3 copy -16 bitshift putu16
  198.   exch 2 add exch 16#ffff and putu16
  199. } bind def
  200.  
  201. % <string> .strtoint <integer>
  202. /.strtoint {
  203.   0 exch { exch 8 bitshift add } forall
  204. } bind def
  205.  
  206. % <nametable> <nameid> findname <string> true
  207. % <nametable> <nameid> findname false
  208. /findname {
  209.   DEBUG { (findname: ) print dup =only  } if
  210.   false 3 1 roll 0 1 3 index 2 getu16 1 sub {
  211.         % Stack: false table id index
  212.     12 mul 6 add 2 index exch 12 getinterval
  213.     dup 6 getu16 2 index eq {
  214.         % We found the name we want.
  215.       exch pop
  216.         % Stack: false table record
  217.       dup 10 getu16 2 index 4 getu16 add
  218.       1 index 8 getu16 4 -1 roll 3 1 roll getinterval exch
  219.         % Stack: false string record
  220.         % Check for 8- vs. 16-bit characters.
  221.       is2byte { string2to1 } if true null 4 -1 roll exit
  222.     } if pop
  223.   } for pop pop
  224.   DEBUG {
  225.     dup { ( = ) print 1 index == } { ( not found) = } ifelse
  226.   } if
  227. } bind def
  228.  
  229. % <namerecord> is2byte <bool>
  230. /is2byte {
  231.   dup 0 getu16 {
  232.     { pop true }        % Apple Unicode
  233.     { pop false }        % Macintosh Script manager
  234.     { 1 getu16 1 eq }        % ISO
  235.     { 1 getu16 1 eq }        % Microsoft
  236.   } exch get exec
  237. } bind def
  238.  
  239. % <string2> string2to1 <string>
  240. /string2to1 {
  241.   dup length 2 idiv string dup
  242.   0 1 3 index length 1 sub {
  243.     3 index 1 index 2 mul 1 add get put dup
  244.   } for pop exch pop
  245. } bind def
  246.  
  247. % <array> <lt-proc> sort <array>
  248. /sort {
  249.   1 index length 1 sub -1 1 {
  250.     2 index exch 2 copy get 3 copy    % arr proc arr i arr[i] arr i arr[i]
  251.     0 1 3 index 1 sub {
  252.       3 index 1 index get    % arr proc arr i arr[i] arr imax amax j arr[j]
  253.       2 index 1 index 10 index exec {    % ... amax < arr[j]
  254.     4 2 roll
  255.       } if pop pop
  256.     } for            % arr proc arr i arr[i] arr imax amax
  257.     4 -1 roll exch 4 1 roll put put
  258.   } for pop
  259. } def
  260.  
  261. % <array|string> <index> <count> .safegetinterval <subarray|substring>
  262. /.safegetinterval {
  263.   exch 2 index length .min exch
  264.   2 index length 2 index sub .min
  265.   getinterval
  266. } bind def
  267.  
  268. % <array> <index> <obj> .safeput -
  269. /.safeput {
  270.   2 index length 2 index gt { put } { pop pop pop } ifelse
  271. } bind def
  272.  
  273. % Each procedure in this dictionary is called as follows:
  274. %       <encodingtable> proc <glypharray>
  275. /cmapformats mark
  276.   0 {        % Apple standard 1-to-1 mapping.
  277.     6 256 getinterval { } forall 256 packedarray
  278.   } bind
  279.   2 {        % Apple 16bit CJK (ShiftJIS etc)
  280.  
  281.     % /sHK_sz        subHeaderKey_size    % 1 * uint16
  282.     % /sH_sz        subHeader_size        % 4 * uint16
  283.     % /sH_len        subHeader_length
  284.     % /cmapf2_tblen    total table length
  285.     % /cmapf2_lang    language code (not used)
  286.     % /sHKs        subHeaderKeys
  287.  
  288.     /sHK_sz 2 def
  289.     /sH_sz 8 def
  290.     dup 2 getu16 /cmapf2_tblen exch def
  291.  
  292.     TTCMAP2_DEBUG {
  293.        (format2 table length: 0x) print
  294.        cmapf2_tblen 16 10 string cvrs print
  295.        (=) print
  296.        cmapf2_tblen == flush
  297.     } if
  298.     dup 4 getu16 /cmapf2_lang exch def
  299.  
  300.     TTCMAP2_DEBUG {
  301.        (format2 lang code: 0x) print
  302.        cmapf2_lang 16 10 string cvrs == flush
  303.     } if
  304.     dup 6 256 sHK_sz mul getinterval /sHKs exch def
  305.     TTCMAP2_DEBUG {
  306.        (format2 subHeaderKeys: ) print
  307.        sHKs == flush
  308.        (scan subHeaderKeys\n) print flush
  309.     } if
  310.  
  311.     0        % initialization value for /sH_len
  312.     0 1 255 {
  313.        TTCMAP2_DEBUG {
  314.           (hi byte ) =only
  315.           dup 16 10 string cvrs =only
  316.           (-> subHeader #) print
  317.           flush
  318.        } if
  319.        sHKs exch
  320.        2 mul getu16
  321.        TTCMAP2_DEBUG {
  322.           dup 16 10 string cvrs =only
  323.           ( ) print dup == flush
  324.        } if
  325.        1 index    % get current max
  326.        1 index    % get current subHeaderKey
  327.        lt {exch} if pop
  328.     } for
  329.     /sH_len exch def
  330.  
  331.     TTCMAP2_DEBUG {
  332.       (format2 subHeader length: ) print
  333.       sH_len ==
  334.       flush
  335.     } if
  336.     dup 6 256 sHK_sz mul add
  337.     cmapf2_tblen 1 index sub getinterval
  338.     /sH_gIA exch def
  339.     TTCMAP2_DEBUG {
  340.        (format2 subHeaders + GID array: ) print
  341.        sH_gIA ==
  342.     } if
  343.  
  344.     /cmapf2_glyph_array 65535 array def
  345.  
  346.     /.cmapf2_putGID {
  347.         /cmapf2_ch cmapf2_ch_hi 8 bitshift cmapf2_ch_lo add def
  348.         TTCMAP2_DEBUG {
  349.             (code: ) =only cmapf2_ch 16 4 string cvrs =only
  350.             ( -> ) =only
  351.         } if
  352.         firstCode cmapf2_ch_lo le
  353.         cmapf2_ch_lo firstCode entryCount add lt
  354.         and { % true: j is inside
  355.             sH_offset idRangeOffset add        % offset to gI
  356.             cmapf2_ch_lo firstCode sub 2 mul    % rel. pos. in range
  357.             add 6 add                % offset in sH_gIA
  358.             sH_gIA exch getu16
  359.             dup 0 gt { % 
  360.                 TTCMAP2_DEBUG {
  361.                     dup 16 8 string cvrs =only
  362.                     (+) =only idDelta 16 8 string cvrs =only
  363.                 } if
  364.                 idDelta add
  365.                 TTCMAP2_DEBUG {
  366.                     (=) =only dup 16 8 string cvrs == flush
  367.                 } if
  368.                 cmapf2_glyph_array exch cmapf2_ch exch put
  369.             } {
  370.                 TTCMAP2_DEBUG {(specified 0: 0\n) print flush} if
  371.                 pop
  372.                 % cmapf2_glyph_array cmapf2_ch 0 put
  373.             } ifelse
  374.         } {   % false: j is outside
  375.             TTCMAP2_DEBUG {(outside of range: 0\n) print flush} if
  376.             % cmapf2_glyph_array cmapf2_ch 0 put
  377.         } ifelse
  378.     } def
  379.  
  380.     16#00 1 16#ff { % hi_byte scan
  381.         /cmapf2_ch_hi exch def
  382.         sHKs cmapf2_ch_hi sHK_sz mul getu16
  383.         TTCMAP2_DEBUG {
  384.             (subHeader_offset = idx * 8 = ) print
  385.             dup ==
  386.         } if
  387.         /sH_offset exch def
  388.         sH_gIA sH_offset sH_sz getinterval
  389.             dup 0 getu16 /firstCode exch def
  390.             dup 2 getu16 /entryCount exch def
  391.             dup 4 gets16 /idDelta exch def
  392.             dup 6 getu16 /idRangeOffset exch def
  393.         pop
  394.         TTCMAP2_DEBUG {
  395.            (idRangeOffset: ) print idRangeOffset 16 8 string cvrs ==
  396.         } if
  397.         sH_offset 0 eq {
  398.            /cmapf2_ch_lo cmapf2_ch_hi def
  399.            /cmapf2_ch_hi 0 def
  400.            .cmapf2_putGID
  401.         } {
  402.            16#00 1 16#ff { % lo_byte scan
  403.                /cmapf2_ch_lo exch def
  404.                .cmapf2_putGID
  405.            } for
  406.         } ifelse
  407.      } for
  408.      pop
  409.      0 1 cmapf2_glyph_array length 1 sub { % rewrite null -> 0.
  410.         % TTCMAP2_DEBUG { (rewriting null: ) print dup == flush } if
  411.         dup cmapf2_glyph_array exch get
  412.         null eq { cmapf2_glyph_array exch 0 put } {pop} ifelse 
  413.      } for
  414.      TTCMAP2_DEBUG { (rewriting finished\n) print flush } if
  415.      cmapf2_glyph_array
  416.      TTCMAP2_DEBUG {
  417.        16#0000 16#0010 16#fff0 {
  418.           16#0000 16#0001 16#000f {
  419.              1 index add dup 16#ffff lt {
  420.                2 index exch get =only
  421.                ( ) =only
  422.              } { pop } ifelse
  423.           } for
  424.           pop
  425.           (\n) print flush
  426.        } for
  427.      } if
  428.   } bind
  429.   4 {        % Microsoft/Adobe segmented mapping.
  430.     /etab exch def
  431.     /nseg2 etab 6 getu16 def
  432.     14 /endc etab 2 index nseg2 getinterval def
  433.         % The Apple TrueType documentation omits the 2-byte
  434.         % 'reserved pad' that follows the endCount vector!
  435.     2 add
  436.     nseg2 add /startc etab 2 index nseg2 getinterval def
  437.     nseg2 add /iddelta etab 2 index nseg2 getinterval def
  438.     nseg2 add /idroff etab 2 index nseg2 getinterval def
  439.         % The following hack allows us to properly handle
  440.         % idiosyncratic fonts that start at 0xf000:
  441.     pop
  442.     /firstcode startc 0 getu16 16#ff00 and dup 16#f000 ne { pop 0 } if def
  443.     /putglyph {
  444.       glyphs code 3 -1 roll put /code code 1 add def
  445.     } bind def
  446.         % Do a first pass to compute the size of the glyphs array.
  447.     /numcodes 0 def /glyphs 0 0 2 nseg2 3 sub {
  448.         % Stack: /glyphs numglyphs i2
  449.       /i2 exch def
  450.       /scode startc i2 getu16 def
  451.       /ecode endc i2 getu16 def
  452.       numcodes scode firstcode sub
  453.         % Hack for fonts that have only 0x0000 and 0xf000 ranges
  454.       %dup 16#e000 ge { 255 and } if
  455.       % the previous line is obstructive to CJK fonts, so it was removed
  456.       exch sub 0 .max ecode scode sub 1 add add
  457.       exch 1 index add exch
  458.       numcodes add /numcodes exch def
  459.     } for array def
  460.         % Now fill in the array.
  461.     /numcodes 0 def /code 0 def
  462.     0 2 nseg2 3 sub {
  463.       /i2 exch def
  464.       /scode startc i2 getu16 def
  465.       /ecode endc i2 getu16 def
  466.       numcodes scode firstcode sub
  467.         % Hack for fonts that have only 0x0000 and 0xf000 ranges
  468.       %dup 16#e000 ge { 255 and } if
  469.       % the previous line is obstructive to CJK fonts, so it was removed
  470.       exch sub 0 .max dup { 0 putglyph } repeat
  471.       ecode scode sub 1 add add numcodes add /numcodes exch def
  472.       /delta iddelta i2 gets16 def
  473.       DEBUG {
  474.     (scode=) print scode =only
  475.     ( ecode=) print ecode =only
  476.     ( delta=) print delta =only
  477.     ( droff=) print idroff i2 getu16 =
  478.       } if
  479.       idroff i2 getu16 dup 0 eq {
  480.     pop scode delta add 65535 and 1 ecode delta add 65535 and
  481.     { putglyph } for
  482.       } {    % The +2 is for the 'reserved pad'.
  483.         /gloff exch 14 nseg2 3 mul add 2 add i2 add add def
  484.         0 1 ecode scode sub {
  485.       2 mul gloff add etab exch getu16
  486.       dup 0 ne { delta add 65535 and } if putglyph
  487.     } for
  488.       } ifelse
  489.     } for glyphs /glyphs null def    % for GC
  490.   } bind
  491.   6 {        % Single interval lookup.
  492.     dup 6 getu16 /firstcode exch def dup 8 getu16 /ng exch def
  493.     firstcode ng add array
  494.         % Stack: tab array
  495.         % Fill elements 0 .. firstcode-1 with 0
  496.     0 1 firstcode 1 sub { 2 copy 0 put pop } for
  497.     dup firstcode ng getinterval
  498.         % Stack: tab array subarray
  499.         % Fill elements firstcode .. firstcode+nvalue-1 with glyph values
  500.     0 1 ng 1 sub {
  501.       dup 2 mul 10 add 4 index exch getu16 3 copy put pop pop
  502.     } for pop exch pop
  503.   } bind
  504. .dicttomark readonly def                % cmapformats
  505.  
  506. % <cmaptab> cmaparray <glypharray>
  507. /cmaparray {
  508.   dup 0 getu16
  509.  
  510.   cmapformats exch .knownget {
  511.     DEBUG {
  512.       (cmap: format ) print 1 index 0 getu16 = flush
  513.     } if exec
  514.   } {
  515.     (Can't handle format ) print 0 getu16 = flush
  516.     0 1 255 { } for 256 packedarray
  517.   } ifelse
  518.   DEBUG {
  519.     (cmap: length=) print dup length = dup ==
  520.   } if
  521. } bind def
  522.  
  523. % Each procedure in this dictionary is called as follows:
  524. %       posttable <<proc>> glyphencoding
  525. /postformats mark
  526.   16#00010000  {    % 258 standard Macintosh glyphs.
  527.     pop MacGlyphEncoding
  528.   }
  529.   16#00020000  {    % Detailed map, required by Microsoft fonts.
  530.     /postglyphs exch def
  531.       postglyphs 32 getu16 /numglyphs exch def
  532.       /glyphnames numglyphs 2 mul 34 add def
  533.       [ 0 1 numglyphs 1 sub {
  534.     2 mul 34 add postglyphs exch getu16
  535.     dup 258 lt {
  536.       MacGlyphEncoding exch get
  537.     } {
  538.       dup 32768 ge {
  539.         % According to the published TrueType spec, such values are
  540.         % "reserved for future use", but at least some PDF files
  541.         % produced by the Adobe PDF library contain entries with a
  542.         % value of 16#ffff.
  543.         pop /.notdef
  544.       } {
  545.         258 sub glyphnames exch {
  546.           postglyphs 1 index get 1 add add
  547.         } repeat
  548.         1 add postglyphs exch 2 copy 1 sub get getinterval cvn
  549.         % At least some of Microsoft's TrueType fonts use incorrect
  550.         % (Adobe-incompatible) names for some glyphs.
  551.         % Correct for this here.
  552.         postremap 1 index .knownget { exch pop } if
  553.       } ifelse
  554.     } ifelse
  555.       } for ]
  556.   } bind
  557.   16#00030000  {    % No map.
  558.     pop [ ]
  559.   } bind
  560. .dicttomark readonly def                % postformats
  561.  
  562. % Each procedure in this dictionary is called as follows:
  563. %    <file> <length> -proc- <string|array_of_strings>
  564. % Note that each table must have an even length, because of a strange
  565. % Adobe requirement that each sfnts entry have even length.
  566. /readtables mark
  567.     % Ordinary tables
  568.   (cmap) { .readtable }
  569.   (head) 1 index
  570.   (hhea) 1 index
  571.   (maxp) 1 index
  572.   (name) 1 index
  573.   (OS/2) 1 index
  574.   (post) 1 index
  575.   (vhea) 1 index
  576.     % Big tables
  577.   (glyf) { .readbigtable }
  578.   (loca) 1 index
  579.   (hmtx) 1 index
  580.   (vmtx) 1 index
  581.     % Tables only needed for embedding in PDF files
  582.   (cvt ) { .readtable }
  583.   (fpgm) 1 index
  584.   (prep) 1 index
  585.   (GSUB) 1 index
  586. .dicttomark
  587. % Normally there would be a 'readonly' here, but the ttf2pf utility wants
  588. % to include the 'kern' table as well, so we leave the readtables dictionary
  589. % writable.
  590. def                % readtables
  591.  
  592. % Read a table as a single string.
  593. % <file> <length> .readtable <string>
  594. /.readtable {
  595.   dup dup 1 and add string
  596.         % Stack: f len str
  597.   dup 0 4 -1 roll getinterval
  598.         % Stack: f str str1
  599.     % Because of the absurd PostScript specification that gives an
  600.     % error for reading into an empty string, we have to check for
  601.     % this explicitly here.
  602.   3 -1 roll exch
  603.   dup () ne { readstring } if pop pop
  604. } bind def
  605.  
  606. % Read a big table (one that may exceed 64K).
  607. % <file> <length> .readbigtable <string[s]>
  608. /.readbigtable {
  609.   dup 65400 lt {
  610.     .readtable
  611.   } {
  612.     currentuserparams /VMReclaim get -2 vmreclaim
  613.     [ 4 2 roll {
  614.         % Stack: mark ... f left
  615.       dup maxstring le { exit } if
  616.       1 index maxstring string readstring pop 3 1 roll maxstring sub
  617.     } loop .readtable ]
  618.     exch vmreclaim
  619.   } ifelse
  620. } bind def
  621.  
  622. end readonly def                % .loadttfontdict
  623.  
  624. % <tab> .printtab -
  625. /.printtab {
  626.   dup 0 4 getinterval print ( ) print
  627.   dup 8 getu32 =only ( ) print
  628.   12 getu32 =
  629. } bind def
  630.  
  631. % <file> .loadttfonttables -
  632. % <file> <fontindex> .loadttfonttables - % extention by hideyuki
  633. % Pushes .loadttfontdict & scratch dict on d-stack.
  634. % Defines f, offsets, tables, tabdict, tabs.
  635. /.loadttfonttables {
  636.   .loadttfontdict begin
  637.   40 dict begin
  638.   dup type /integertype eq % extention by hideyuki
  639.   { 1 sub } { 0 } ifelse /findex exch def
  640.   /f exch def
  641.   /offsets f 12 string readstring pop def
  642.  
  643.   % TrueType Collection File support
  644.   % Jan 11 2000: Hideyuki Suzuki <hideyuki@sat.t.u-tokyo.ac.jp>
  645.   % Feb 10 2001: suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
  646.   offsets 0 4 getinterval (ttcf) eq {
  647.     [ 1 1 offsets 8 getu32 { pop f 4 string readstring pop 0 getu32} for ]
  648.     dup findex get dup /ttcheader exch def exch length 4 mul 12 add sub
  649.     %dup 0 gt { string f exch readstring pop } if pop
  650.     f fileposition add f exch setfileposition
  651.     % the previous line is for very large ttcf, hacked by suzuki toshiya
  652.     /offsets f 12 string readstring pop def
  653.   } { /ttcheader 0 def } ifelse
  654.  
  655.   /tables f offsets 4 getu16 16 mul string readstring pop def
  656.   /tabdict tables length 16 idiv dict def
  657.     % tabs = tables we want to keep, sorted by file position.
  658.   /tabs [ 0 16 tables length 1 sub {
  659.     tables exch 16 getinterval
  660.     DEBUG { dup .printtab } if
  661.     dup 0 4 getinterval readtables 1 index known {
  662.       tabdict exch 2 index put
  663.     } {
  664.       pop pop
  665.     } ifelse
  666.   } for ] {
  667.     exch 8 getu32 exch 8 getu32 lt
  668.   } sort def
  669.     % In certain malformed TrueType fonts, tables overlap.
  670.     % Truncate tables if necessary.
  671.   0 1 tabs length 2 sub {
  672.     dup tabs exch get exch 1 add tabs exch get
  673.     1 index 8 getu32 2 index 12 getu32 add
  674.     1 index 8 getu32 gt {
  675.       (**** Warning: ) print 1 index 0 4 getinterval print
  676.       ( overlaps ) print dup 0 4 getinterval print
  677.       (, truncating.) = flush
  678.       dup 8 getu32 2 index 8 getu32 sub
  679.       2 index 12 3 -1 roll putu32
  680.     } if pop pop
  681.   } for
  682. } bind def
  683.  
  684. % - .readttdata -
  685. % Read data.  Updates offsets, tabs; stores data in tabdict.
  686. /.readttdata {
  687.  
  688.   % TrueType Collection File support
  689.   % Jan 11 2000: Hideyuki Suzuki <hideyuki@sat.t.u-tokyo.ac.jp>
  690.   % /fpos offsets length tables length add def
  691.   /fpos ttcheader offsets length tables length add add def
  692.   /sfpos offsets length tabs length 16 mul add def
  693.   offsets 4 tabs length putu16
  694.   tabs {
  695.     dup 0 4 getinterval /tname exch def
  696.     dup 8 getu32 /tpos exch def
  697.     dup 12 getu32 /tlen exch def
  698.     8 sfpos putu32
  699.     % Skip data between the end of the previous table and
  700.     % the beginning of this one, if any.
  701.     tpos fpos gt {
  702.       f tpos fpos sub () /SubFileDecode filter dup flushfile closefile
  703.       /fpos tpos def
  704.     } if
  705.     f tlen readtables tname get exec
  706.     tabdict tname 3 -1 roll put
  707.     /fpos fpos tlen add def
  708.     % Round up the table length to an even value.
  709.     /sfpos sfpos tlen dup 1 and add add def
  710.   } forall
  711. } bind def
  712.  
  713. % Find the string in a list of strings that includes a given index.
  714. % <strings> <index> .findseg <string> <index'>
  715. /.findseg {
  716.   exch {
  717.     dup length 2 index gt { exch exit } if
  718.     length sub
  719.   } forall
  720. } bind def
  721.  
  722. % - .makesfnts -
  723. % Defines checksum, getloca, head, locatable, numloca, post, sfnts, upem
  724. /.makesfnts {
  725.   .readttdata
  726.   /head tabdict /head get def
  727.   /locatable tabdict /loca get def
  728.   /post tabdict /post .knownget not { null } if def
  729.   /numloca
  730.     locatable dup type /stringtype eq
  731.      { length }
  732.      { 0 exch { length add } forall }
  733.     ifelse    % no def yet
  734.   locatable type /stringtype eq {
  735.     /.indexloca {} def
  736.   } {
  737.     /.indexloca /.findseg load def
  738.   } ifelse
  739.   head 50 getu16 0 ne {
  740.     /getloca {
  741.       2 bitshift locatable exch .indexloca getu32
  742.     } def
  743.     4 idiv 1 sub
  744.   } {
  745.     /getloca {
  746.       dup add locatable exch .indexloca getu16 dup add
  747.     } def
  748.     2 idiv 1 sub
  749.   } ifelse def        % numloca
  750.     % If necessary, re-partition the glyfs.
  751.   tabdict /glyf get dup type /stringtype ne {
  752.     .dividesfnts tabdict /glyf 3 -1 roll put
  753.   } {
  754.     pop
  755.   } ifelse
  756.   /sfnts [
  757.     offsets tabs { concatstrings } forall
  758.     tabs {
  759.       0 4 getinterval tabdict exch get
  760.       dup type /stringtype ne { aload pop } if
  761.     } forall
  762.   ] def
  763. } bind def
  764.  
  765. % <glyfs> .dividesfnts <glyfs'>
  766. /.dividesfnts {
  767.   /glyfs exch def
  768.   /len1 0 glyfs { length add } forall def
  769.         % Determine where to split the glyfs by scanning loca.
  770.         % The very last entry in loca may be bogus.
  771.         % Note that some loca entries may be odd, but we can only
  772.         % split at even positions.
  773.         %
  774.         % Construct splitarray, the array of final lengths of
  775.         % the sfnts entries covering the glyfs (i.e., all but
  776.         % the first and last sfnts entries).
  777.     /prevsplit 0 def
  778.     /prevboundary 0 def
  779.     /prevoddboundary 0 def % see TYPE42_NO_ODDSIZE_STR in zfont42.c
  780.     /splitarray [
  781.       0 1 numloca 1 sub {
  782.     getloca dup prevsplit maxstring add gt {
  783.           prevboundary prevsplit eq { % see TYPE42_NO_ODDSIZE_STR in zfont42.c
  784.              /ferr (%stderr) (w) file def
  785.              ferr (glyf table ) writestring
  786.              ferr prevsplit 10 string cvs writestring
  787.              ferr ( - ) writestring
  788.              dup 10 string cvs ferr exch writestring
  789.              ferr ( too long segment without suitable boundary.\n)
  790.              writestring
  791.              ferr closefile
  792.              /prevboundary prevoddboundary def
  793.           } if
  794.           DEBUG {
  795.              dup 10 string cvs print
  796.              ( segment is longer than maxstring, split now ) print
  797.              prevboundary 10 string cvs print
  798.              ( - ) print
  799.              prevsplit 10 string cvs print
  800.              (\n) print
  801.           } if
  802.       prevboundary prevsplit sub exch
  803.       /prevsplit prevboundary def
  804.           % /prevoddboundary 0 def
  805.     } if
  806.     dup 1 and 0 eq { % see TYPE42_NO_ODDSIZE_STR in zfont42.c
  807.           DEBUG {
  808.             dup 10 string cvs print
  809.             ( \() print
  810.             dup prevsplit sub 10 string cvs print
  811.             (\) ) print
  812.             ( even length OK\n) print
  813.     } if
  814.           /prevboundary exch def
  815.           % /prevoddboundary 0 def
  816.         } {
  817.           DEBUG {
  818.             dup 10 string cvs print
  819.             ( \() print
  820.             dup prevsplit sub 10 string cvs print
  821.             (\) ) print
  822.             ( odd length!\n) print
  823.     } if
  824.           % prevoddboundary 0 eq {
  825.             /prevoddboundary exch def
  826.           % } { pop } ifelse
  827.         } ifelse
  828.         % dup 0 eq { (why ZERO?\n) print } if
  829.         % dup ==
  830.       } for
  831.       len1 prevsplit sub
  832.     ] def
  833.     currentuserparams /VMReclaim get -2 vmreclaim
  834.     [
  835.         % Re-split the sfnts glyfs strings according to splitarray.
  836.         % We do this by iterating over the final segments defined
  837.         % by splitarray, and constructing them from pieces of the
  838.         % current glyfs strings.  We recycle the current strings
  839.         % when possible, to avoid stressing the allocator.
  840.       /sfnt_idx 0 def
  841.       /strpos 0 def
  842.       /avail () def
  843.       splitarray {
  844.     /seglen exch def
  845.     /segpos 0 def
  846.     avail length seglen ge
  847.       { avail 0 seglen getinterval /avail () def } { seglen string }
  848.     ifelse
  849.     {
  850.       /str glyfs sfnt_idx get def
  851.       /strlen str length def
  852.       /strleft strlen strpos sub def
  853.       seglen segpos sub strleft lt { exit } if
  854.         % Copy the (rest of the) string into the new segment.
  855.         % We know strleft <= segleft.
  856.       dup segpos str strpos strleft getinterval putinterval
  857.       /segpos segpos strleft add def
  858.       /avail str def
  859.       /sfnt_idx sfnt_idx 1 add def
  860.       /strpos 0 def
  861.       segpos seglen eq { exit } if
  862.     } loop
  863.         % Fill up the segment with an initial piece of the next
  864.         % existing glyfs string.  We know strleft > segleft.
  865.     /segleft seglen segpos sub def
  866.     dup segpos str strpos segleft getinterval putinterval
  867.     /strpos strpos segleft add def
  868.       } forall
  869.     ]
  870.     exch vmreclaim
  871. } bind def
  872.  
  873. % - .getpost -
  874. % Uses post, defines glyphencoding
  875. /.getpost {
  876.   /glyphencoding post null eq {
  877.     DEBUG { (post missing) = flush } if [ ]
  878.   } {
  879.     postformats post 0 getu32 .knownget {
  880.       DEBUG {
  881.     (post: format ) print
  882.     post 0 getu16 =only (,) print post 2 getu16 = flush
  883.       } if
  884.       post exch exec
  885.     } {
  886.       DEBUG { (post: unknown format ) print post 0 getu32 = flush } if [ ]
  887.     } ifelse
  888.   } ifelse def
  889. } bind def
  890.  
  891. % - .ttkeys <key> <value> ...
  892. /.ttkeys {
  893.   count /ttkeycount exch def
  894.   /upem head 18 getu16 def
  895.   /FontMatrix matrix
  896.   /FontBBox [ 36 2 42 { head exch gets16 upem div } for ]
  897.   nextxuid
  898.   tabdict /name .knownget {
  899.         % Find the names from the 'name' table.
  900.     /names exch def
  901.     /FontName names 6 findname not { curxuid 16 8 string cvrs } if
  902.       /fontname 1 index def
  903.     /FontInfo mark
  904.       names 0 findname { /Notice exch } if
  905.       names 1 findname { /FamilyName exch } if
  906.       names 4 findname { /FullName exch } if
  907.       names 5 findname { /Version exch } if
  908.   } {
  909.         % No name table, fabricate a FontName.
  910.     /FontName curxuid 16 8 string cvrs
  911.       /fontname 1 index def
  912.     /FontInfo mark
  913.   } ifelse
  914.   DEBUG { (fontname ) print fontname = } if
  915.         % Stack: ... /FontInfo mark key1 value1 ...
  916.   post null ne {
  917.     /ItalicAngle post 4 gets32 65536.0 div
  918.     /isFixedPitch post 12 getu32 0 ne
  919.     /UnderlinePosition post 8 gets16 upem div
  920.     /UnderlineThickness post 10 gets16 upem div
  921.   } if
  922.   counttomark 0 ne { .dicttomark } { pop pop } ifelse
  923.   /XUID [orgXUID 42 curxuid]
  924.   DEBUG {
  925.     tabs { .printtab } forall
  926.     [ sfnts { length } forall ] ==
  927.     count ttkeycount sub array astore dup { == } forall aload pop
  928.   } if
  929.   /sfnts sfnts
  930. } bind def
  931.  
  932. % ---------------- Standard TrueType font loading ---------------- %
  933.  
  934. % - .pickcmap -
  935. % Defines cmapsub, cmaptab
  936. /.pickcmap {
  937.   tabdict /cmap get
  938.         % The Apple cmap format is no help in determining the encoding.
  939.         % Look for a Microsoft table.  If we can't find one,
  940.         % just use the first table, whatever it is.
  941.   dup 4 8 getinterval exch             % the default
  942.   0 1 2 index 2 getu16 1 sub {
  943.     8 mul 4 add 1 index exch 8 getinterval
  944.     dup 0 getu16 /cmap_platform exch def
  945.     dup 2 getu16 /cmap_encoding exch def
  946.     DEBUG {
  947.       (cmap: platform ) print cmap_platform =only
  948.       ( encoding ) print cmap_encoding = flush
  949.     } if
  950.     cmap_platform 3 eq { exch 3 -1 roll pop exit } if pop
  951.   } for
  952.         % Stack: subentry table
  953.   /cmapsub 2 index def
  954.   exch 4 getu32 1 index length 1 index sub getinterval
  955.   /cmaptab exch def
  956. } bind def
  957.  
  958. % <glyph> .nname <_name>
  959. /.nname {
  960.   =string cvs (_) exch concatstrings cvn
  961. } bind def
  962.  
  963. % - .charkeys /CharStrings <charstrings> /Encoding <encoding>
  964. % Resets glyphencoding
  965. /.charkeys {
  966.   DEBUG {
  967.     (glyphencoding: length=) print glyphencoding dup length = === flush
  968.   } if
  969.         % Hack: if there is no usable post table but the cmap uses
  970.         % the Microsoft Unicode encoding, use ISOLatin1Encoding.
  971.   glyphencoding length 0 eq cmapsub 0 4 getinterval <00030001> eq and {
  972.     /glyphencoding ISOLatin1Encoding dup length array copy def
  973.   } if
  974.         % If necessary, fabricate additional glyphencoding entries
  975.         % to cover all of loca, or truncate glyphencoding.
  976.   glyphencoding length numloca lt {
  977.     /glyphencoding [ glyphencoding aload pop
  978.     counttomark 1 numloca 1 sub { .nname } for ] def
  979.   } {
  980.     /glyphencoding glyphencoding 0 numloca getinterval def
  981.   } ifelse
  982.         % Some badly designed Chinese fonts have a post table
  983.         % in which all glyphs other than 0 are named .null.
  984.         % Use CharStrings to keep track of the reverse map from
  985.         % names to glyphs, and don't let any name be used for
  986.         % more than one glyph.
  987.   /CharStrings glyphencoding dup length 1 add dict    % +1 for .notdef
  988.     0 1 3 index length 1 sub {
  989.         % Stack: glyphencoding dict index
  990.       2 index 1 index get 2 index 1 index known {
  991.         % The same name maps to more than one glyph.
  992.         % Change the name.
  993.     pop dup .nname 3 index 2 index 2 index put
  994.       } if
  995.       2 index exch 3 -1 roll put
  996.     } for exch pop
  997.         % If there is no .notdef entry, map it to glyph 0.
  998.   dup /.notdef known not { dup /.notdef 0 put } if
  999.   readonly
  1000.   /Encoding
  1001.     [ cmaptab cmaparray dup length 256 gt { 0 256 getinterval } if
  1002.     { glyphencoding exch get } forall
  1003.     counttomark 256 exch sub { /.notdef } repeat ]
  1004.   DEBUG { (Encoding: ) print dup === flush } if
  1005. } bind def
  1006.  
  1007. % -mark- <key> <value> ... .definettfont <font>
  1008. /.definettfont {
  1009.   /FontType 42
  1010.   /PaintType 0
  1011.   DEBUG {
  1012.     (numloca=) print numloca =
  1013.   } if
  1014.   .dicttomark
  1015.   end end dup /FontName get exch definefont
  1016. } bind def
  1017.  
  1018. % <file> .loadttfont <type42font>
  1019. /.loadttfont {
  1020.   .loadttfonttables
  1021.   .makesfnts
  1022.   .getpost
  1023.   .pickcmap
  1024.   mark
  1025.   .charkeys
  1026.   .ttkeys
  1027.   .definettfont
  1028. } bind def
  1029.  
  1030. % ---------------- CIDFontType 2 font loading ---------------- %
  1031.  
  1032. % Create a string with array of CIDs
  1033. % [ <cid1> ... <cidN> ] .makecidmapstring <string>
  1034. /.makecidmapstring {
  1035.   mark exch cvx exec counttomark        % mark 1..N len
  1036.   dup 2 mul string                % mark 1..N len s
  1037.   dup 3 -1 roll 1 sub 2 mul -2 0 {        % mark 1..N s s
  1038.     2 copy 5 index -8 bitshift put        % mark 1..N s s j2
  1039.     1 add 4 -1 roll 16#ff and put dup        % mark 1..N-1 s s
  1040.   } for pop                    % mark s
  1041.   exch pop                    % s
  1042. } bind def
  1043.  
  1044. % Create a string or an array of strings with array of CIDs
  1045. % [ <cid1> ... <cidN> ] .makecidmap <string>|[<string> ...]
  1046. %   written by Taiji Yamada <taiji@aihara.co.jp>
  1047. /.makecidmap {
  1048.   dup length maxstring le {
  1049.     .makecidmapstring
  1050.   } {
  1051.     dup length dup maxstring idiv exch
  1052.     maxstring mod 0 ne { 1 add } if array exch
  1053.     0 1 3 index length 1 sub {
  1054.       dup maxstring mul 1 index 1 add maxstring mul
  1055.       3 index length .min 1 index sub
  1056.       3 index 3 1 roll getinterval
  1057.       .makecidmapstring
  1058.       3 index 3 1 roll put
  1059.     } for pop
  1060.   } ifelse
  1061. } bind def
  1062.  
  1063. % <file> .loadttcidfont <cidtype2font>
  1064. /.loadttcidfont {
  1065.   .loadttfonttables
  1066.   .makesfnts
  1067.     % CIDFontType2 fonts don't have a cmap: they are indexed by CID.
  1068.   /.ttencmapproc false def
  1069.   mark
  1070.   .ttkeys
  1071.   .definettcidfont
  1072. } bind def
  1073.  
  1074. % - .getgsub -
  1075. % Defines gsubh, gsubv, gsubh2v and also defines gsubver, gsubfmt
  1076. %   in the case that GSUB table has 'Single Substitution Format 2'
  1077. %   which is formally used for vertically oriented glyphs such as CJK fonts.
  1078. % Written by Hideyuki Suzuki <hideyuki@sat.t.u-tokyo.ac.jp>
  1079. % Modified by Taiji Yamada <taiji@aihara.co.jp>
  1080. %
  1081. % [GSUB - The Glyph Substitution Table]
  1082. % Index    Size    Type    Name of Entry
  1083. % -----------------------------------
  1084. % 0    4    Fixed    Version
  1085. % 4    2    Offset    ScriptList
  1086. % 6    2    Offset    FeatureList
  1087. % 8    2    Offset    LookupList
  1088. %
  1089. % [Single Substitution Format 2, Subtable at LookupList]
  1090. % Index    Size    Type    Name of Entry
  1091. % -----------------------------------
  1092. % 0    2    uint16    SubstFormat
  1093. % 4    2    Offset    Coverage(--)
  1094. % 6    2    uint16    GlyphCount
  1095. % 8    2    GlyphID    Substitute(vertically oriented glyphs)
  1096. % --    2    uint16    SubstFormat
  1097. % +2    2    uint16    GlyphCount(same as above GlyphCount)
  1098. % +4    2    GlyphID    GlyphArray(horizontally oriented glyphs)
  1099. % -----------------------------------
  1100. % References
  1101. % 1. http://www.microsoft.com/typography/OTSPEC/gsub.htm
  1102. %
  1103. /.getgsub {
  1104.   /gsubhog null def
  1105.   /gsubvog null def
  1106.   /gsubh2v null def
  1107.   tabdict /GSUB .knownget { % if
  1108.     dup /gsubver exch 0 getu32 def
  1109.     %dup /gsubosl exch 4 getu16 12 add def
  1110.     %dup /gsubofl exch 6 getu16 12 add def
  1111.     dup /gsuboll exch 8 getu16 12 add def
  1112.     DEBUG {
  1113.       (gsubver: ) print gsubver =
  1114.       %(gsubosl: ) print gsubosl =
  1115.       %(gsubofl: ) print gsubofl =
  1116.       (gsuboll: ) print gsuboll =
  1117.     } if
  1118.     dup /gsubfmt exch gsuboll 0 add getu16 def
  1119.     DEBUG {
  1120.       (gsubfmt: ) print gsubfmt =
  1121.     } if
  1122. %    gsubver 16#00010000 eq { % ifelse
  1123.       gsubfmt 2 eq { % ifelse
  1124.     dup /gsubocv exch gsuboll 2 add getu16 def
  1125.     dup /gsubglc exch gsuboll 4 add getu16 def
  1126.     % hacked by suzuki toshiya at 2001/3/6
  1127.     %dup /gsubvog exch gsuboll 6 add gsubglc getinterval def
  1128.     %dup /gsubhog exch gsuboll gsubocv add 4 add gsubglc getinterval def
  1129.     dup /gsubvog exch gsuboll 6 add gsubglc 2 mul getinterval def
  1130.     dup /gsubhog exch gsuboll gsubocv add 4 add gsubglc 2 mul getinterval def
  1131.     DEBUG {
  1132.       (gsubocv: ) print gsubocv =
  1133.       (gsubglc: ) print gsubglc =
  1134.  
  1135.       (gsubhog->gsubvog ) =
  1136.       0 2 gsubhog length 2 sub { % for
  1137.         dup
  1138.         gsubhog exch getu16 =only
  1139.         (->) =only
  1140.         gsubvog exch getu16 =
  1141.       } for
  1142.     } if
  1143.     /gsubh2v << 0 2 gsubhog length 2 sub {
  1144.       dup gsubhog exch getu16
  1145.       exch gsubvog exch getu16
  1146.     } for >> def
  1147.       } {
  1148.     %(UNKNOWN GSUB FORMAT.) = flush
  1149.       } ifelse
  1150. %    } {
  1151. %      (ILLEGAL GSUB VERSION.) = flush
  1152. %    } ifelse
  1153.     pop
  1154.   } if
  1155. } bind def
  1156.  
  1157. % glyphid .gsublookup glyphid
  1158. % Lookup substitute table. return the origin if not found.
  1159. %   modified by Taiji Yamada <taiji@aihara.co.jp> and Hideyuki Suzuki
  1160. /.gsublookup {
  1161.   dup gsubh2v exch .knownget { exch pop } if
  1162. } bind def
  1163.  
  1164. % - .getos2 -
  1165. % Defines os2ver, os2cp1, os2cp2
  1166. %   to detect the kind of CID with the OS/2 table of a TrueType font.
  1167. % Written by Taiji Yamada <taiji@aihara.co.jp>
  1168. %
  1169. % [OS/2 - OS/2 and Windows Metrics]
  1170. % Index    Size    Type    Name of Entry
  1171. % -----------------------------------
  1172. % 0    2    USHORT    version
  1173. % 2    2    SHORT    xAvgCharWidth
  1174. % 4    2    USHORT    usWeightClass
  1175. % 6    2    USHORT    usWidthClass
  1176. % 8    2    SHORT    fsType
  1177. % 10    2    SHORT    ySubscriptXSize
  1178. % 12    2    SHORT    ySubscriptYSize
  1179. % 14    2    SHORT    ySubscriptXOffset
  1180. % 16    2    SHORT    ySubscriptYOffset
  1181. % 18    2    SHORT    ySuperscriptXSize
  1182. % 20    2    SHORT    ySuperscriptYSize
  1183. % 22    2    SHORT   ySuperscriptXOffset
  1184. % 24    2    SHORT    ySuperscriptYOffset
  1185. % 26    2    SHORT    yStrikeoutSize
  1186. % 28    2    SHORT    yStrikeoutPosition
  1187. % 30    2    SHORT    sFamilyClass
  1188. % 32    10    BYTE    panose[10]
  1189. % 42    4    ULONG    ulUnicodeRange1
  1190. % 46    4    ULONG    ulUnicodeRange2
  1191. % 50    4    ULONG    ulUnicodeRange3
  1192. % 54    4    ULONG    ulUnicodeRange4
  1193. % 58    4    CHAR    achVendID[4]
  1194. % 62    2    USHORT    fsSelection
  1195. % 64    2    USHORT    usFirstCharIndex
  1196. % 66    2    USHORT    usLastCharIndex
  1197. % 68    2    SHORT    sTypoAscender
  1198. % 70    2    SHORT    sTypoDescender
  1199. % 72    2    SHORT    sTypoLineGap
  1200. % 74    2    USHORT    usWinAscent
  1201. % 76    2    USHORT    usWinDescent
  1202. % 78    4    ULONG    ulCodePageRange1
  1203. % 82    4    ULONG    ulCodePageRange2
  1204. % 86    2    SHORT    sxHeight
  1205. % 88    2    SHORT    sCapHeight
  1206. % 90    2    USHORT    usDefaultChar
  1207. % 92    2    USHORT    usBreakChar
  1208. % 94    2    USHORT    usMaxContext
  1209. % -----------------------------------
  1210. % References
  1211. % 1. http://www.microsoft.com/typography/OTSPEC/os2.htm
  1212. %
  1213. /.getos2 {
  1214.   /os2ver 0 def
  1215.   tabdict (OS/2) cvn .knownget { % if
  1216.     dup /os2ver exch 0 getu16 def
  1217.     os2ver 0 gt { % if
  1218.       %dup /os2typ exch 8 gets16 def
  1219.       %dup /os2fam exch 30 gets16 def
  1220.       dup /os2ur1 exch 42 getu32 def
  1221.       dup /os2ur2 exch 46 getu32 def
  1222.       dup /os2ur3 exch 50 getu32 def
  1223.       dup /os2ur4 exch 54 getu32 def
  1224.       %dup /os2sel exch 62 getu16 def
  1225.       %dup /os2fci exch 64 getu16 def
  1226.       %dup /os2lci exch 64 getu16 def
  1227.       dup /os2cp1 exch 78 getu32 def 
  1228.       dup /os2cp2 exch 82 getu32 def
  1229.       DEBUG {
  1230.     /tmp 64 string def
  1231.     (os2ver: ) print os2ver 2 tmp cvrs =
  1232.     %(os2typ: ) print os2typ 2 tmp cvrs =
  1233.     %(os2fam: ) print os2fam 2 tmp cvrs =
  1234.     (os2ur1: ) print os2ur1 2 tmp cvrs =
  1235.     (os2ur2: ) print os2ur2 2 tmp cvrs =
  1236.     (os2ur3: ) print os2ur3 2 tmp cvrs =
  1237.     (os2ur4: ) print os2ur4 2 tmp cvrs =
  1238.     %(os2sel: ) print os2sel 2 tmp cvrs =
  1239.     %(os2fci: ) print os2fci 2 tmp cvrs =
  1240.     %(os2lci: ) print os2lci 2 tmp cvrs =
  1241.     (os2cp1: ) print os2cp1 2 tmp cvrs =
  1242.     (os2cp2: ) print os2cp2 2 tmp cvrs =
  1243.     [
  1244.       [ 1 0 bitshift (Latin 1)    ]
  1245.       [ 1 1 bitshift (Latin 2)    ]
  1246.       [ 1 2 bitshift (Cyrillic)    ]
  1247.       [ 1 3 bitshift (Greek)    ]
  1248.       [ 1 4 bitshift (Turkish)    ]
  1249.       [ 1 5 bitshift (Hebrew)    ]
  1250.       [ 1 6 bitshift (Arabic)    ]
  1251.       [ 1 7 bitshift (Baltic)    ]
  1252.       [ 1 8 bitshift (Vietnamese)    ]
  1253.       [ 1 16 bitshift (Thai)    ]
  1254.       [ 1 17 bitshift (Japanese)    ]
  1255.       [ 1 18 bitshift (Simplified Chinese)    ]
  1256.       [ 1 19 bitshift (Korean Wansung)    ]
  1257.       [ 1 20 bitshift (Traditional Chinese)    ]
  1258.       [ 1 21 bitshift (Korean Johab)    ]
  1259.       [ 1 31 bitshift (Symbol)    ]
  1260.     ] { % forall
  1261.       dup 0 get os2cp1 and 0 gt { % if
  1262.         (CodePage: ) print 1 get =
  1263.       } {
  1264.           pop
  1265.       } ifelse
  1266.     } forall
  1267.       } if
  1268.     } if
  1269.     pop
  1270.   } if
  1271. } bind def
  1272.  
  1273. % ---------------- PDF TrueType font loading ---------------- %
  1274.  
  1275. % Strictly speaking, this code should be loaded only if we have a PDF
  1276. % interpreter, but it's so closely tied to the rest of the code in this
  1277. % file that we always include it.
  1278.  
  1279. % <plat+enc> .findcmap <subtable> true
  1280. % <plat+enc> .findcmap false
  1281. /.findcmap {
  1282.   false exch tabdict /cmap get
  1283.         % Some fonts have multiple cmaps with the same platform and
  1284.         % encoding.  Use the first one we find.
  1285.   0 1 2 index 2 getu16 1 sub {
  1286.         % Stack: false plat+enc cmap index
  1287.     8 mul 4 add 1 index exch 8 getinterval 
  1288.     dup 0 4 getinterval 3 index eq {
  1289.       4 getu32 1 index exch 1 index length 1 index sub getinterval
  1290.       4 -1 roll not 4 2 roll exit
  1291.     } if pop
  1292.   } for
  1293.         % Stack: false plat+enc cmap || subtable true plat+enc cmap
  1294.   pop pop
  1295. } bind def
  1296.  
  1297. % <subcmap> <chartoglyphmap> .pdfmapchars
  1298. %   /CharStrings <charstrings> /Encoding <encoding>
  1299. % Uses encoding
  1300. /.pdfmapchars {
  1301.   exch cmaparray /cmapencoding exch def
  1302.     % Invert glyphencoding (post).
  1303.   /inversepost glyphencoding length dict def
  1304.   0 1 glyphencoding length 1 sub {
  1305.     glyphencoding 1 index get exch inversepost 3 1 roll put
  1306.   } for
  1307.   /CharStrings mark 3 -1 roll {
  1308.     dup type /arraytype eq {
  1309.       exch /ch exch def { ch exch .pdfaddchar } forall
  1310.     } {
  1311.       .pdfaddchar
  1312.     } ifelse
  1313.   } forall
  1314.     % Add a .notdef => 0 entry if needed.  Per Adobe's spec,
  1315.     % .dicttomark (>>) adds pairs in top-to-bottom order.
  1316.   /.notdef 0
  1317.   .dicttomark
  1318.   /Encoding encoding
  1319. } bind def
  1320. % <charname> <charcode> .pdfaddchar <charname> <glyph#>
  1321. % <charname> <charcode> .pdfaddchar -
  1322. /.pdfaddchar {
  1323.   dup cmapencoding length lt {
  1324.     cmapencoding exch get dup 0 eq {
  1325.       pop .pdfaddpost
  1326.     } if
  1327.   } {
  1328.     pop .pdfaddpost
  1329.   } ifelse
  1330. } bind def
  1331. % <charname> .pdfaddpost <charname> <glyph#>
  1332. % <charname> .pdfaddpost -
  1333. /.pdfaddpost {
  1334.   inversepost 1 index .knownget not { pop } if
  1335. } bind def
  1336.  
  1337. % - .pdfcharkeys /CharStrings <charstrings> /Encoding <encoding>
  1338. /.pdfcharkeys {
  1339.     % The following algorithms are per the PDF Reference, Second Edition
  1340.     % (PDF 1.3 reference manual).
  1341.   encoding null eq {
  1342.     .charkeys        % use default algorithm
  1343.   } {
  1344.     <00030001> .findcmap {
  1345.       AdobeGlyphList .pdfmapchars
  1346.     } {
  1347.       <00010000> .findcmap {
  1348.     .romanmacdict .pdfmapchars
  1349.       } {
  1350.     .charkeys    % use default algorithm
  1351.       } ifelse
  1352.     } ifelse
  1353.   } ifelse
  1354. } bind def
  1355.  
  1356. % <file> <encoding|null> .loadpdfttfont <type42font>
  1357. /.loadpdfttfont {
  1358.   exch .loadttfonttables
  1359.   /encoding exch def
  1360.   .makesfnts
  1361.   .getpost
  1362.   .pickcmap
  1363.   mark
  1364.   .pdfcharkeys
  1365.   .ttkeys
  1366.   .definettfont
  1367. } bind def
  1368.  
  1369. % ---------------- CJK TrueType font loading ---------------- %
  1370.  
  1371. % Written by the gs-cjk project
  1372.  
  1373. % .parsecmap
  1374. % push an array as a result of reading a CMap file.
  1375. % the array is of the following form.
  1376. %   [ [ [ dst src num ] [ dst src num ] ... [ dst src num ] ]
  1377. %     [ [ dst src num ] [ dst src num ] ... [ dst src num ] ]
  1378. %     ...
  1379. %     [ [ dst src num ] [ dst src num ] ... [ dst src num ] ] ]
  1380. % each array [dst src num] corresponds to each line within
  1381. % /begin{bf,cid}{char,range}/end{bf,cid}{char,range} pairs.
  1382.  
  1383. /.parsecmapdict mark
  1384.  
  1385.   % override system operators
  1386.   /findresource { pop } bind
  1387.   /defineresource { pop pop } bind
  1388.   /dict {}
  1389.   /def { pop pop } bind
  1390.   /dup null
  1391.   /begin { pop } bind
  1392.   /end {}
  1393.   /currentdict null
  1394.  
  1395.   % override CMap operators
  1396.   /usecmap { pop } bind
  1397.   /CMapName null
  1398.   /begincmap { [ } bind
  1399.   /endcmap { ] } bind
  1400.   /begincodespacerange { pop mark } bind
  1401.   /endcodespacerange { cleartomark } bind
  1402.   /beginnotdefrange { pop mark } bind
  1403.   /endnotdefrange { cleartomark } bind
  1404.   /beginbfchar { /parsecmapcounter exch def } bind    % for FromCID CMaps
  1405.   /endbfchar {
  1406.     parsecmapcounter dup array exch 1 sub -1 0 {
  1407.       [ 5 3 roll exch .strtoint 1 ]
  1408.       2 index 3 1 roll put
  1409.     } for
  1410.   } bind
  1411.   /beginbfrange { begincidrange }                       % for FromCID CMaps
  1412.   /endbfrange { endcidrange }
  1413.   /begincidchar { beginbfchar }                % for ToCID CMaps
  1414.   /endcidchar { endbfchar }
  1415.   /begincidrange { /parsecmapcounter exch def } bind    % for ToCID CMaps
  1416.   /endcidrange {
  1417.     parsecmapcounter dup array exch 1 sub -1 0 {
  1418.       [ 6 3 roll 3 1 roll .strtoint exch .strtoint exch 1 index sub 1 add ]
  1419.       2 index 3 1 roll put
  1420.     } for
  1421.   } bind
  1422.  
  1423.   % misc
  1424.   /parsecmapcounter 0
  1425.  
  1426. .dicttomark def         % .parsecmapdict
  1427.  
  1428.  
  1429. /.parsecmapfname 100 string def
  1430.  
  1431. % <CMapName> .parsecmap <array>
  1432. % Return the contents of the CMap.  If the CMap is not found, empty array
  1433. % is returned.  Note that usecmap is ignored because of efficiency.
  1434. /.parsecmap {
  1435.   /CMap /Category findresource begin
  1436.   //.parsecmapfname ResourceFileName end        % filename
  1437.   dup status {
  1438.     pop pop pop pop
  1439.     .parsecmapdict begin run end
  1440.   } {
  1441.     pop []
  1442.   } ifelse
  1443. } bind def
  1444.  
  1445. % .buildcmaptab
  1446. % construct a cmap table using information obtained from horizontal/vertical
  1447. % CMaps, ToUnicode CMap, and substition data.
  1448.  
  1449. % cmap /CMap proc .applyCMap cmap
  1450. /.applyCMap {
  1451.   exch .parsecmap            % {} [[[].].]
  1452.   dup length 1 sub -1 0 {        % {} [[[].].] len-1 -1 0 {} for
  1453.     1 index exch get            % {} [[[].].] [[].]
  1454.     dup length 1 sub -1 0 {        % {} [[[].].] [[].] len-1 -1 0 for {}
  1455.       1 index exch get            % {} [[[].].] [[].] [ cid gid num ]
  1456.       cvx exec cmapglyphs        % {} [[[].].] [[].] cid gid num gmap
  1457.       3 1 roll .safegetinterval {    % {} [[[].].] [[].] cid [gid'..]
  1458.     4 index exec dup cmapglyphs 0 get eq {
  1459.       % found no glyph
  1460.       pop
  1461.     } {
  1462.       % found a glyph
  1463.       5 index exch 2 index exch .safeput
  1464.     } ifelse
  1465.     1 add                % {} [[[].].] [[].] cid++
  1466.       } forall pop
  1467.     } for                % {} [[[].].] [[].]
  1468.     pop                    % {} [[[].].]
  1469.   } for                    % {} [[[].].]
  1470.   pop pop                %
  1471. } bind def
  1472.  
  1473. % cmap /CMap-V .applyvCMap cmap
  1474. /.applyvCMap {
  1475.   gsubh2v null ne {
  1476.     { .gsublookup } .applyCMap
  1477.   } {
  1478.     { } .applyCMap
  1479.   } ifelse
  1480. } bind def
  1481.  
  1482. % cmap /CMap-H .applyhCMap cmap
  1483. /.applyhCMap {
  1484.   { } .applyCMap
  1485. } bind def
  1486.  
  1487. % cmap /CMap-V .applyvCMapUnicode cmap
  1488. /.applyvCMapUnicode {
  1489.   gsubh2v null ne {
  1490.     {
  1491.       dup 16#f900 ge
  1492.       1 index 16#ff00 ge 2 index 16#ff9f le and not
  1493.       and not {
  1494.         .gsublookup
  1495.       } if
  1496.     } bind .applyCMap
  1497.   } {
  1498.     { } .applyCMap
  1499.   } ifelse
  1500. } bind def
  1501.  
  1502. % cmap /Adobe-*-* .applyCIDToCode cmap
  1503. /.applyCIDToCode {
  1504.   .parsecmap
  1505.   {
  1506.     {                           % cmap [ dist cid num ]
  1507.       dup 0 get length 2 gt {   % multi-byte dist is not supported yet.
  1508.     pop
  1509.       } {
  1510.         cvx exec exch           % cmap dist num cid
  1511.         cmapglyphs 4 2 roll     % cmap cid cmapglyphs dist num
  1512.         exch .strtoint exch
  1513.         .safegetinterval        % cmap cid subcmapglyphs
  1514.         {                       % cmap cid gid
  1515.           2 index 2 index       % cmap cid gid cmap cid
  1516.           3 2 roll              % cmap cid cmap cid gid
  1517.           .safeput              % cmap cid
  1518.           1 add                 % cmap nextcid
  1519.         } forall pop
  1520.       } ifelse
  1521.     } forall
  1522.   } forall
  1523. } bind def
  1524.  
  1525. % cmap /Adobe-*-UCS2 .applyCIDToUnicode cmap
  1526. /.applyCIDToUnicode {
  1527.   .parsecmap
  1528.   {
  1529.     {                           % cmap [ distuni cid num ]
  1530.       dup 0 get length 2 gt     % multi-byte dist is not supported yet.
  1531.       1 index 0 get <fffd> eq   % the value <fffd> is regard as undefined code.
  1532.       or {
  1533.     pop
  1534.       } {
  1535.         cvx exec exch           % cmap distuni num cid
  1536.         cmapglyphs 4 2 roll     % cmap cid cmapglyphs distuni num
  1537.         exch .strtoint exch     % cmap cid cmapglyphs distuni num
  1538.         .safegetinterval        % cmap cid subcmapglyphs
  1539.         {                       % cmap cid gid
  1540.           2 index 2 index       % cmap cid gid cmap cid
  1541.           3 2 roll              % cmap cid cmap cid gid
  1542.           .safeput              % cmap cid
  1543.           1 add                 % cmap nextcid
  1544.         } forall pop
  1545.       } ifelse
  1546.     } forall
  1547.   } forall
  1548. } bind def
  1549.  
  1550. /.buildcmapdict mark
  1551.   /Adobe-CNS1 <<
  1552.     /Registry (Adobe)
  1553.     /Ordering (CNS1)
  1554.     /CIDCounts [ 14099 17408 17601 18846 18962 ]
  1555.     /Big5 { 0 {
  1556.       /Adobe-CNS1-ETen-B5 .applyCIDToCode
  1557.       /ETen-B5-V .applyvCMap
  1558.       /ETen-B5-H .applyhCMap
  1559.     } }
  1560.     /Unicode { 3 {
  1561.       /Adobe-CNS1-UCS2 .applyCIDToUnicode
  1562.       /UniCNS-UCS2-V .applyvCMapUnicode
  1563.       /UniCNS-UCS2-H .applyhCMap
  1564.     } }
  1565.   >>
  1566.   /Adobe-GB1 <<
  1567.     /Registry (Adobe)
  1568.     /Ordering (GB1)
  1569.     /CIDCounts [ 7717 9897 22127 22353 29064 ]
  1570.     /PRC { 2 {
  1571.       /Adobe-GB1-GBK-EUC .applyCIDToCode
  1572.       /GBK-EUC-V .applyvCMap
  1573.       /GBK-EUC-H .applyhCMap
  1574.     } }
  1575.     /Unicode { 4 {
  1576.       /Adobe-GB1-UCS2 .applyCIDToUnicode
  1577.       /UniGB-UCS2-V .applyvCMapUnicode
  1578.       /UniGB-UCS2-H .applyhCMap
  1579.     } }
  1580.   >>
  1581.   /Adobe-Japan1 <<
  1582.     /Registry (Adobe)
  1583.     /Ordering (Japan1)
  1584.     /CIDCounts [ 8284 8359 8720 9354 15444 ]
  1585.     /ShiftJIS { 2 {
  1586.       /Adobe-Japan1-90ms-RKSJ .applyCIDToCode
  1587.       /90ms-RKSJ-V .applyvCMap
  1588.       /90ms-RKSJ-H .applyhCMap
  1589.     } }
  1590.     /Unicode { 4 {
  1591.       /Adobe-Japan1-UCS2 .applyCIDToUnicode
  1592.       /UniJIS-UCS2-V .applyvCMapUnicode
  1593.       /UniJIS-UCS2-H .applyhCMap
  1594.     } }
  1595.   >>
  1596.   /Adobe-Japan2 <<
  1597.     /Registry (Adobe)
  1598.     /Ordering (Japan2)
  1599.     /CIDCounts [ 6068 ]
  1600.     /Unicode { 0  {
  1601.       /UniHojo-UCS2-V .applyvCMapUnicode
  1602.       /UniHojo-UCS2-H .applyhCMap
  1603.     } }
  1604.   >>
  1605.   /Adobe-Korea1 <<
  1606.     /Registry (Adobe)
  1607.     /Ordering (Korea1)
  1608.     /CIDCounts [ 9333 18155 18352 ]
  1609.     /Johab { 1 {
  1610.       /KSC-Johab-V .applyvCMap
  1611.       /KSC-Johab-H .applyhCMap
  1612.     } }
  1613.     /Unicode { 2 {
  1614.       /Adobe-Korea1-UCS2 .applyCIDToUnicode
  1615.       /UniKS-UCS2-V .applyvCMapUnicode
  1616.       /UniKS-UCS2-H .applyhCMap
  1617.     } }
  1618.     /Wansung { 1 {
  1619.       /Adobe-Korea1-KSCms-UHC .applyCIDToCode
  1620.       /KSCms-UHC-V .applyvCMap
  1621.       /KSCms-UHC-H .applyhCMap
  1622.     } }
  1623.   >>
  1624.   /Identity <<    % ttcmap ordering CIDMap only for specific and rare CJK TTF
  1625.     /Registry (Unregistered)    % Thus Registry value is unpredictable. This
  1626.     /Ordering (Identity)    % CIDFont can be used with Identity-H|V CMap
  1627.     /CIDCounts [ 65535 ]
  1628.     /H { 0 {
  1629.       /Identity-H .applyhCMap    % for ttcmap-order CIDMap
  1630.     } }
  1631.     /V { 0 {
  1632.       /Identity-H .applyvCMap    % for ttcmap-order and vertically-used CIDMap
  1633.     } }
  1634.   >>
  1635. .dicttomark def
  1636.  
  1637. /.ttencmap <<
  1638.   /Identity              false
  1639.   /Auto                  { .ttencoding {
  1640.                              dup .ttcharset exch get exec exch true
  1641.                            } { false } ifelse
  1642.                          } bind
  1643.   /Adobe-CNS1            { /Adobe-CNS1   .ttencoding }
  1644.   /Adobe-GB1             { /Adobe-GB1    .ttencoding }
  1645.   /Adobe-Japan1          { /Adobe-Japan1 .ttencoding }
  1646.   /Adobe-Japan2          { /Adobe-Japan2 .ttencoding }
  1647.   /Adobe-Korea1          { /Adobe-Korea1 .ttencoding }
  1648.   /Adobe-CNS1-Big5       { /Adobe-CNS1   /Big5     true }
  1649.   /Adobe-CNS1-Unicode    { /Adobe-CNS1   /Unicode  true }
  1650.   /Adobe-GB1-PRC         { /Adobe-GB1    /PRC      true }
  1651.   /Adobe-GB1-Unicode     { /Adobe-GB1    /Unicode  true }
  1652.   /Adobe-Japan1-ShiftJIS { /Adobe-Japan1 /ShiftJIS true }
  1653.   /Adobe-Japan1-Unicode  { /Adobe-Japan1 /Unicode  true }
  1654.   /Adobe-Japan2-Unicode  { /Adobe-Japan2 /Unicode  true }
  1655.   /Adobe-Korea1-Johab    { /Adobe-Korea1 /Johab    true }
  1656.   /Adobe-Korea1-Unicode  { /Adobe-Korea1 /Unicode  true }
  1657.   /Adobe-Korea1-Wansung  { /Adobe-Korea1 /Wansung  true }
  1658.   /Identity-H            { /Identity     /H        true }
  1659.   /Identity-V            { /Identity     /V        true }
  1660. >> def
  1661.  
  1662. /.ttcharset <<
  1663.   /Unicode  { .detectos2 }
  1664.   /ShiftJIS /Adobe-Japan1
  1665.   /Big5     /Adobe-CNS1
  1666.   /PRC      /Adobe-GB1
  1667.   /Wansung  /Adobe-Korea1
  1668.   /Johab    /Adobe-Korea1
  1669. >> def
  1670.  
  1671. /.ttencdict <<
  1672.   <00030001> /Unicode
  1673.   <00030002> /ShiftJIS
  1674.   <00030003> /Big5
  1675.   <00030004> /PRC
  1676.   <00030005> /Wansung
  1677.   <00030006> /Johab
  1678. >> def
  1679.  
  1680. /.ttencoding {
  1681.   .ttencdict cmapsub 0 4 getinterval .knownget
  1682. } bind def
  1683.  
  1684. /.ttos2tab [
  1685.   [ 1 20 bitshift /Adobe-CNS1   ]
  1686.   [ 1 18 bitshift /Adobe-GB1    ]
  1687.   [ 1 17 bitshift /Adobe-Japan1 ]
  1688.   [ 1 19 bitshift /Adobe-Korea1 ]
  1689.   [ 1 21 bitshift /Adobe-Korea1 ]
  1690. ] def
  1691.  
  1692. /.detectos2 {
  1693.   /Identity    % default linear ordering to GID, Adobe Identity CIDs
  1694.   os2ver 0 gt {
  1695.     .ttos2tab {
  1696.       dup 0 get os2cp1 and 0 ne {
  1697.         1 get exch
  1698.       } if pop
  1699.     } forall
  1700.   } if
  1701. } bind def
  1702.  
  1703. % /Charset /TTEncoding .buildcmaptab cmap
  1704. /.buildcmaptab {
  1705.   .buildcmapdict 3 2 roll get begin
  1706.   cvx exec exch CIDCounts end exch get array
  1707.   dup length 1 sub 0 1 3 -1 roll { 1 index exch cmapglyphs 0 get put } for
  1708.   exch exec
  1709. } bind def
  1710.  
  1711. % -mark- <key> <value> ... .definettcidfont <font>
  1712. %   rapid version of .definecjkvttcidfont
  1713. % Proposed by Hideyuki Suzuki <hideyuki@sat.t.u-tokyo.ac.jp>
  1714. % Modified by Taiji Yamada <taiji@aihara.co.jp>
  1715. /.definettcidfont {
  1716.   /CIDFontName fontname
  1717.   /CIDFontType 2
  1718.   /CIDSystemInfo
  1719.   mark .ttencmapproc {
  1720.     .buildcmapdict 3 2 roll get begin
  1721.     cvx exec pop
  1722.     /Supplement exch
  1723.     /Registry Registry
  1724.     /Ordering Ordering
  1725.     end
  1726.   } {
  1727.     /Registry (Adobe)
  1728.     /Ordering (Identity)    % pursuant to makeIdentityCMap in pdf_font.ps
  1729.     /Supplement 0
  1730.   } ifelse
  1731.   .dicttomark
  1732.   /CharStrings mark /.notdef 0 .dicttomark
  1733.   .ttencmapproc {
  1734.     /cmapglyphs cmaptab cmaparray def
  1735.     exec .buildcmaptab
  1736.     dup length /CIDCount exch
  1737.     3 -1 roll .makecidmap    % it has not supported a dictionary yet
  1738.     /CIDMap exch        % it should be a string or an array of strings
  1739.   } {
  1740.     /CIDCount numloca
  1741.     /CIDMap 0    % an integer interpreted as an offset from GI (see #5012 p.16)
  1742.   } ifelse
  1743.   /GDBytes 2
  1744.   .dicttomark
  1745.   end end dup /CIDFontName get exch /CIDFont defineresource
  1746. } bind def
  1747.  
  1748. % Load a TrueType font from a file as a CIDFontType 2 font.
  1749. %   rapid version of .loadcjkvttcidfont
  1750. % Proposed by Hideyuki Suzuki <hideyuki@sat.t.u-tokyo.ac.jp>
  1751. % Modified by Taiji Yamada <taiji@aihara.co.jp>
  1752. %
  1753. % <file>             .loadttcidfont <cidtype2font>
  1754. % <file> <fontindex> .loadttcidfont <cidtype2font>
  1755. %   detect a kind of CID and encode a TrueType font to a CID-Keyed font.
  1756. %
  1757. % <file>             <ttcidcode> .loadttcidfont <cidtype2font>
  1758. % <file> <fontindex> <ttcidcode> .loadttcidfont <cidtype2font>
  1759. %   load a TrueType font and encode it with the kind of CID described
  1760. %   in <ttcidcode> which is one of entry in .ttencmap.
  1761. /.loadcjkvttcidfont {
  1762.   dup type /nametype ne { /Auto } if
  1763.   1 index type /integertype eq { 3 1 roll } { exch } ifelse
  1764.   .loadttfonttables
  1765.   .makesfnts
  1766.   .pickcmap    % when we can't pick a Microsoft cmap table, do what to do
  1767.   .getgsub
  1768.   .getos2       % we need an OS/2 table for CJKV TrueType fonts (by taiji)
  1769.   .ttencmap exch get /.ttencmapproc exch def
  1770.   mark
  1771.   .ttkeys
  1772.   .definettcidfont
  1773. } bind def
  1774.  
  1775. % Open and load a TrueType font from a file as a CIDFontType 2 font.
  1776. % <filename>             .openttcidfont <cidtype2font>
  1777. % <filename> <fontindex> .openttcidfont <cidtype2font>
  1778. % <filename>             <ttcidcode> .openttcidfont <cidtype2font>
  1779. % <filename> <fontindex> <ttcidcode> .openttcidfont <cidtype2font>
  1780. /.openttcidfont {
  1781.   1 dup index type /nametype eq { 1 add } if
  1782.   dup index type /integertype eq { 1 add } if
  1783.   dup 1 add -1 roll (r) file exch 1 roll
  1784.   .loadcjkvttcidfont    % rapid version, since 20010316
  1785. } bind def
  1786.